package com.xb.loan.cashier.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xb.loan.cashier.biz.dao.bean.CashierChargeOrder;
import com.xb.loan.cashier.biz.dao.bean.CashierPayChannel;
import com.xb.loan.cashier.biz.dao.bean.CashierPlat;
import com.xb.loan.cashier.biz.dao.bean.CashierPlatPaytype;
import com.xb.loan.cashier.biz.pay.IPaymentForCharge;
import com.xb.loan.cashier.biz.pay.PaymentChargeManager;
import com.xb.loan.cashier.biz.pay.alipay.AlipayErrorCode;
import com.xb.loan.cashier.biz.pay.alipay.AlipayPayment;
import com.xb.loan.cashier.biz.pay.alipay.AlipayPaymentForCharge;
import com.xb.loan.cashier.biz.pay.alipay.util.AlipayNotify;
import com.xb.loan.cashier.biz.pay.bankcomm.util.BankcommCore;
import com.xb.loan.cashier.biz.pay.bean.PaymentChargeOrder;
import com.xb.loan.cashier.biz.pay.unionpay.UnionPayAcpService;
import com.xb.loan.cashier.biz.pay.unionpay.UnionPayConstants;
import com.xb.loan.cashier.biz.pay.unionpay.UnionPayment;
import com.xb.loan.cashier.biz.pay.wechat.WeChatConst;
import com.xb.loan.cashier.biz.pay.wechat.util.WeChatSignature;
import com.xb.loan.cashier.biz.service.CashierChargeOrderService;
import com.xb.loan.cashier.biz.service.CashierPayChannelService;
import com.xb.loan.cashier.biz.service.CashierPlatPaytypeService;
import com.xb.loan.cashier.biz.service.CashierPlatService;
import com.xb.loan.cashier.biz.service.cache.RedisMethodCacheSupport;
import com.xb.loan.cashier.biz.task.TaskManagerFactory;
import com.xb.loan.cashier.biz.task.plat.PushChargeTask;
import com.xb.loan.cashier.biz.util.Configure;
import com.xb.loan.cashier.biz.util.XMLUtil;
import com.xb.loan.cashier.service.IChargeOrderService;
import com.xb.loan.cashier.service.bean.*;
import com.xb.loan.cashier.service.bean.*;
import com.xb.loan.cashier.service.constant.ICashierEnumConst;
import com.xb.loan.cashier.service.exception.ICashierServiceException;
import com.xb.loan.encryptor.crypt.Encryptor;
import com.xb.loan.encryptor.crypt.EncryptorManager;
import com.xb.loan.log.exception.BizException;
import com.xb.loan.util.DateHelper;
import com.xb.loan.util.SpringHelper;
import com.xb.loan.util.StringUtils;
import com.xb.loan.util.cache.redis.comm.FormatOperation;
import com.xb.loan.util.common.ObjectOperation;
import com.xb.loan.util.json.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;
import java.util.Map.Entry;

/**
 * 充值接口业务实现层
 */
@Service("chargeOrderService")
public class ChargeOrderServiceImpl implements IChargeOrderService {
    
    private static final Logger log = LoggerFactory.getLogger(ChargeOrderServiceImpl.class);
    
    @Autowired
    private CashierPayChannelService cashierPayChannelService;
    
    @Autowired
    private CashierChargeOrderService cashierChargeOrderService;
    
    @Autowired
    private CashierPlatPaytypeService cashierPlatPaytypeService;
    
    @Autowired
    private CashierPlatService cashierPlatService;
    
    // 成功状态
    private final static String SUCC = "success";
    // 失败状态
    private final static String FAIL = "fail";
    
    @Override
    public List<CashierPayChannelBO> queryListByPlatId(String platId, int payType) {
        List<CashierPayChannel> payChannelList = cashierPayChannelService.queryListByPlatId(platId, payType);
        return ObjectOperation.convertByClassesList(payChannelList , CashierPayChannelBO.class);
    }

    @Override
    public ChargeOrderPayBO charge(ChargeOrderBO chargeOrderBo) throws BizException {
    	log.info("charge 接收到的参数："+chargeOrderBo.toString());
    	String orderId = chargeOrderBo.getOrderId();			// 订单号
    	String platId = chargeOrderBo.getPlatId();				// 平台ID
    	int payChannelType = chargeOrderBo.getPayChannelType();	// 第三方支付渠道
    	String payChannelId = "";								// 渠道类型ID
    	
    	// 验证充值参数是否正确，如果有错就抛出相应异常
    	validateChargeParam(chargeOrderBo);
    	
    	// 查询订单是否存在 
    	CashierChargeOrder cashierChargeOrder = cashierChargeOrderService.queryByOrderId(orderId);
    	
    	// 如果存在且处理完则返回错误
        if(cashierChargeOrder != null) {
        	// 获得订单对应的渠道类型ID
        	payChannelId = cashierChargeOrder.getPayChannelId();
        	if(cashierChargeOrder.getStatus() == ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus() // 处理中状态订单跳转到支付宝验证
        			|| cashierChargeOrder.getStatus() == ICashierEnumConst.CashierChargeStatus.FAIL.getStatus()){
        		log.info("charge 订单已存在并且完成,不能重复提交 orderId=" + orderId);
        		throw ICashierServiceException.ORDER_FINISH;
        	}
        } else {
        	log.info("charge 订单号不存在，orderId = " + orderId);
        	// 通过平台id、第三方支付渠道获得对应的渠道ID
        	payChannelId = getChannelID(platId, payChannelType);
        }
        
        // 根据渠道类型ID获取支付渠道相关配置信息
        CashierPayChannel cPayChannel = cashierPayChannelService.queryByChannelId(payChannelId);
		if (cPayChannel == null) {
			log.info("charge 第三方支付渠道信息不存在 payChannelId=" + payChannelId);
			throw ICashierServiceException.PAY_CHANNEL_NOT_EXIST;
		}
		// 根据平台id、支付渠道id查询平台加密方式
        CashierPlatPaytype cPlatPayType = cashierPlatPaytypeService.queryEntity(platId, payChannelId);
        if (cPlatPayType == null) {
        	log.info("charge 平台相关信息不存在 platId=" + platId + ",payChannelId=" + payChannelId);
        	throw ICashierServiceException.PLAT_PAY_GATEWAY_NOT_EXIST;
        }
		// 获得第三方支付URL
        String payURL = getChargetPayURL(chargeOrderBo, cashierChargeOrder, cPayChannel, cPlatPayType);
		if(StringUtils.isEmpty(payURL)) {
			log.info("charge 第三方支付生成支付地址为空，OrderId=" + orderId);
			throw ICashierServiceException.systemException;
		}
		log.info("charge 第三方支付地址 url:" + payURL);
		
		// 订单不存在的时候需要添加订单（创建以第三方支付连接成功后再创建订单）
		if(cashierChargeOrder == null){
			// 通过充值订单请求、支付渠道，生成并插入一条新充值订单
			cashierChargeOrder = insertNewCashierOrder(chargeOrderBo, cPayChannel);
		}
		
		// 封装数据
		ChargeOrderPayBO chargetOrderPay = ObjectOperation.convertByClasses(cashierChargeOrder, ChargeOrderPayBO.class);
		// 第三方渠道请求 是   表单串或url地址
		chargetOrderPay.setPayChannelReq(payURL);
		// 设置渠道业务类型 
		chargetOrderPay.setTradeType(chargeOrderBo.getTradeType());
		// 返回充值订单支付返回信息
    	return chargetOrderPay;
    }
    
    /**
     * 验证充值参数是否正确，如果有错就抛出相应异常
     * 
     * @param chargeOrderBo 充值参数
     * @throws BizException 参数错误异常
     * 2016年6月12日 by lh.qiu
     */
    private void validateChargeParam(ChargeOrderBO chargeOrderBo) throws BizException {
    	// 获取传入参数
    	String orderId = chargeOrderBo.getOrderId();
    	String platId = chargeOrderBo.getPlatId();
    	String partnerId = chargeOrderBo.getPartnerId();
    	String userId = chargeOrderBo.getUserId();
    	double money = chargeOrderBo.getMoney();
    	String accountPeriod = chargeOrderBo.getAccountPeriod();
    	String sign = chargeOrderBo.getSign();
    	
    	// 验证参数是否正确
    	if(StringUtils.isEmpty(orderId)) {
    		throw ICashierServiceException.ORDER_ID_IS_NULL;
    	}
    	if(StringUtils.isEmpty(platId)) {
    		throw ICashierServiceException.PLAT_ID_IS_NULL;
    	}
    	if(StringUtils.isEmpty(partnerId)) {
    		throw ICashierServiceException.PARTNER_ID_IS_NULL;
    	}
    	if(StringUtils.isEmpty(userId)) {
    		throw ICashierServiceException.USER_ID_IS_NULL;
    	}
    	if(StringUtils.isEmpty(accountPeriod)) {
    		throw ICashierServiceException.ACCOUNT_PERIOD_IS_NULL;
    	}
    	if(StringUtils.isEmpty(sign)) {
    		throw ICashierServiceException.SIGN_IS_NULL;
    	}
    	if(money <= 0) {
    		throw ICashierServiceException.MONEY_LESS_THAN_ZERO;
    	}
		
		// --------------------------验证加密串是否正确--------------------------
		//模拟平台加密
        Encryptor encrytor = EncryptorManager.getEncryptor("partner");
        //加密串 sign签名字段：money、platId、userId、orderId、partnerId
        StringBuffer msg = new StringBuffer();
        String split = ICashierEnumConst.EncryptStrCentor.COMMON.getCode();
        msg.append(new DecimalFormat("#0.00").format(money)).append(split);
        msg.append(platId).append(split);
        msg.append(userId).append(split);
        msg.append(orderId).append(split);
        msg.append(partnerId);
        // 加密数据校验
        String encryptId = Configure.getStringValue("encrypt.cashier.id");
        boolean encryptValidate = encrytor.encryptValidate(encryptId, null, msg.toString(), sign);
        if(!encryptValidate) {
        	throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
        }
        // --------------------------验证加密串是否正确--------------------------
    }
    
    /**
     * 通过充值订单请求、支付渠道，生成并插入一条新充值订单
     * 
     * @param chargeOrderBo 充值订单请求
     * @param cPayChannel 支付渠道
     * @throws BizException 插入失败
     * 2016年6月7日 by lh.qiu
     */
	private CashierChargeOrder insertNewCashierOrder(ChargeOrderBO chargeOrderBo,
			CashierPayChannel cPayChannel) throws BizException {
    	//订单不存在的时候需要添加订单 
    	CashierChargeOrder cChargeOrder = new CashierChargeOrder();
        String date = FormatOperation.formatDateToYMDHms14(new Date());
        String id = FormatOperation.assemblySeq("seq_charge_order", 6, date, "");
        cChargeOrder.setCashierOrderId(id);
        cChargeOrder.setOrderId(chargeOrderBo.getOrderId());
        cChargeOrder.setPlatId(chargeOrderBo.getPlatId());
        cChargeOrder.setPartnerId(chargeOrderBo.getPartnerId());
        cChargeOrder.setUserId(chargeOrderBo.getUserId());
        cChargeOrder.setLoginName(chargeOrderBo.getLoginName());
        cChargeOrder.setMoney(chargeOrderBo.getMoney());
        cChargeOrder.setTitle(chargeOrderBo.getTitle());
        cChargeOrder.setContent(chargeOrderBo.getContent());
        cChargeOrder.setAccountDayPlat(chargeOrderBo.getAccountPeriod());
        cChargeOrder.setPayChannelType(cPayChannel.getPaychannelType());
        cChargeOrder.setPayChannelId(cPayChannel.getPayChannelId());
        cChargeOrder.setStatus(ICashierEnumConst.CashierChargeStatus.WAITING.getStatus());
        cChargeOrder.setCreateTime(new Date());
        cChargeOrder.setSign(chargeOrderBo.getSign());
        int count = cashierChargeOrderService.addOrder(cChargeOrder);
		if (count <= 0) {
			log.info("wapChargeConfirm 新增充值记录失败 platId="
					+ chargeOrderBo.getPlatId() + ",partnerId="
					+ chargeOrderBo.getPartnerId() + ",userId="
					+ chargeOrderBo.getUserId() + ",orderId="
					+ chargeOrderBo.getOrderId());
			throw ICashierServiceException.systemException;
		} else {
			log.info("wapChargeConfirm 新增充值记录成功 platId="
					+ chargeOrderBo.getPlatId() + ",partnerId="
					+ chargeOrderBo.getPartnerId() + ",userId="
					+ chargeOrderBo.getUserId() + ",orderId="
					+ chargeOrderBo.getOrderId());
		}
		return cChargeOrder;
    }
    
    /**
     * 通过平台id、第三方支付渠道获得对应的渠道ID
     * 
     * @param platId 平台id
     * @param payChannelType 第三方支付渠道
     * @return 渠道ID
     * 2016年6月7日 by lh.qiu
     */
    private String getChannelID(String platId, int payChannelType) throws BizException{
    	log.info("getChannelID platId="+platId+",payChannelType="+payChannelType);
    	// 根据平台id查询所有可用充值支付渠道
    	List<CashierPayChannelBO> channelList = queryListByPlatId(platId, ICashierEnumConst.CashierPayType.charge.getCode());
    	if(channelList != null && channelList.size() > 0) {
    		for(CashierPayChannelBO channelBo : channelList) {
    			if(channelBo.getPaychannelType() == payChannelType) {
    				return channelBo.getPayChannelId();
    			}
    		}
    	}
    	// 如果没有找到对应的渠道返回支付渠道不存在Exception
    	throw ICashierServiceException.PAY_CHANNEL_NOT_EXIST;
    }
    
    /**
     * 获得第三方支付URL
     * 
     * @param chargeOrderBo 充值订单信息
     * @param cashierChargeOrder 充值订单DB信息
     * @param cPayChannel 支付渠道信息
     * @param cPlatPayType 平台信息
     * @return 第三方支付URL
     * @throws BizException Exception
     * 2016年6月7日 by lh.qiu
     */
	private String getChargetPayURL(ChargeOrderBO chargeOrderBo,
                                    CashierChargeOrder cashierChargeOrder,
                                    CashierPayChannel cPayChannel, CashierPlatPaytype cPlatPayType)
			throws BizException {
		// 第三方支付URL
		String payURL = "";
		try {
			// 通过第三方支付渠道码，得到对应的支付对象实例
			IPaymentForCharge iPayment = PaymentChargeManager.getPaymentGateway(chargeOrderBo.getPayChannelType());
			// 根据充值订单、充值订单DB信息、支付渠道信息、平台加密方式，创建与第三方交互的支付订单信息
			PaymentChargeOrder payOrder = createPaymentChargeOrder(chargeOrderBo, cashierChargeOrder, cPayChannel, cPlatPayType);
			// 统一充值方法（通过支付类型判断调用哪个支付方法，1：web；2：wap；3：app）
			payURL = iPayment.charge(payOrder, chargeOrderBo.getTradeType());
		} catch (Exception e) {
			payURL = null;
			log.error("charge 第三方支付生成支付地址失败，OrderId=" + chargeOrderBo.getOrderId(), e);
			throw ICashierServiceException.systemException;
		}
		return payURL;
	}
    
    /**
     * 根据充值订单、充值订单DB信息、支付渠道信息、平台加密方式，创建与第三方交互的支付订单信息
     * 
     * @param chargeOrderBo 充值订单
     * @param cashierChargeOrder 充值订单DB信息
     * @param cPayChannel 支付渠道信息
     * @param cPlatPayType 平台加密方式
     * @return 与第三方交互的支付订单信息
     * 2016年6月7日 by lh.qiu
     */
	private PaymentChargeOrder createPaymentChargeOrder(
			ChargeOrderBO chargeOrderBo, CashierChargeOrder cashierChargeOrder,
			CashierPayChannel cPayChannel, CashierPlatPaytype cPlatPayType) {
		// 如果DB查询的订单信息不为空，取DB的订单信息；如果DB查询的订单信息为空，取前台传入的订单信息
		String platId = cashierChargeOrder == null ? chargeOrderBo.getPlatId() : cashierChargeOrder.getPlatId();
		String title = cashierChargeOrder == null ? chargeOrderBo.getTitle() : cashierChargeOrder.getTitle();
		String orderId = cashierChargeOrder == null ? chargeOrderBo.getOrderId() : cashierChargeOrder.getOrderId();
		String content = cashierChargeOrder == null ? chargeOrderBo.getContent() : cashierChargeOrder.getContent();
		double money = cashierChargeOrder == null ? chargeOrderBo.getMoney() : cashierChargeOrder.getMoney();
		
		// 根据某些计算，获得第三方交互支付订单的信息
    	String partner = cPayChannel.getChannelUser();
		String subject = StringUtils.isEmpty(title) == true ? "购彩充值" : title;
		String signType = cPlatPayType.getEncryptType() == ICashierEnumConst.CashierEncryptType.MD5.getEncryptType() ? ICashierEnumConst.CashierEncryptType.MD5.getDesc() : ICashierEnumConst.CashierEncryptType.RSA.getDesc();
		String signKey = cPlatPayType.getEncryptType() == ICashierEnumConst.CashierEncryptType.MD5.getEncryptType() ? cPayChannel.getMd5Key() : cPayChannel.getPrivateKey();
		String notifyUrl = cPayChannel.getNotifyUrl() + "/" + platId + "/" + cPayChannel.getPayChannelId() + "/" + chargeOrderBo.getTradeType();
		String returnUrl = StringUtils.isNotEmpty(chargeOrderBo.getCallBackUrl())==true?chargeOrderBo.getCallBackUrl():cPayChannel.getCallBackUrl() + "/" + platId + "/" + cPayChannel.getPayChannelId() + "/" + chargeOrderBo.getTradeType();
		String payUrl = cPayChannel.getPayUrl();
		String payUrlBatch = cPayChannel.getPayUrlBatch();
		String queryUrl = cPayChannel.getQueryUrl();
		String queryUrlBatch = cPayChannel.getQueryUrlBatch();
		String jsonConfig = cPayChannel.getJsonConfig();
		
		// 如果传了用户IP地址（ 微信APP支付时必须传。支付宝和银联支付可以为空），将用户IP地址放入到json中
		if(!StringUtils.isEmpty(chargeOrderBo.getRemoteAddr())) {
			JSONObject json = JsonUtils.fromJson(jsonConfig);
			json.put("remoteAddr", chargeOrderBo.getRemoteAddr());
			jsonConfig = JsonUtils.toJson(json, false);
		}
		
		PaymentChargeOrder payOrder = new PaymentChargeOrder();
		payOrder.setOrderId(orderId);
		payOrder.setChannelUser(partner);
		payOrder.setTitle(subject);
		payOrder.setDetail(content);
		payOrder.setMoney(money);
		payOrder.setSignType(signType);
		payOrder.setSignKey(signKey);
		payOrder.setCallBackUrl(returnUrl);
		payOrder.setPayUrl(payUrl);
		payOrder.setPayUrlBatch(payUrlBatch);
		payOrder.setQueryUrl(queryUrl);
		payOrder.setQueryUrlBatch(queryUrlBatch);
		payOrder.setNotifyUrl(notifyUrl);
		payOrder.setJsonConfig(jsonConfig);
		return payOrder;
    }
	
    @Override
    public ChargeOrderResultBO queryChargeOrder(String orderId) {
        // TODO Auto-generated method stub
        return null;
    }

	@Override
	public CashierPlatBO queryPlatById(String platId) {
		CashierPlat type = RedisMethodCacheSupport.getBean(CashierPlat.class, platId);
        if(type!=null){
            return ObjectOperation.convertByClasses(type, CashierPlatBO.class);
        }
        type = cashierPlatService.queryPlatById(platId);
        if(type==null){
            return null;
        }
        RedisMethodCacheSupport.setBean(CashierPlat.class, type, platId);
        return ObjectOperation.convertByClasses(type, CashierPlatBO.class);
	}

	/**
     * 微信充值异步通知处理
     * @param paramXml
     * @param payChannelId
     * @return
     * @throws BizException
     * @author zljun
     * @date 2016年6月7日
     */
	@Override
	public String wechatChargeNotifyDeal(String paramXml, String payChannelId)
			throws BizException {
		
		// 根据渠道类型查询一条支付渠道
        CashierPayChannel cpc = cashierPayChannelService.queryByChannelId(payChannelId);
        if (cpc == null) {
            log.info("wechatNotify 支付渠道信息不存在 payChannelId=" + payChannelId);
            throw ICashierServiceException.PAY_CHANNEL_NOT_EXIST;
        }
        
		try {
			//先验证签名是否被篡改
			boolean verify_result = WeChatSignature.checkIsSignValidFromResponseString(paramXml, cpc.getMd5Key());
			if(!verify_result){
				//签名验证失败
				log.info("wechatNotify 通知验证失败=" + paramXml);
				throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
			}
		} catch (ParserConfigurationException | IOException | SAXException e) {
			log.error("wechatNotify 通知验证失败=" + paramXml, e);
			throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
		}
        
        //把xml数据转换为map对象，获取订单信息
        Map<String, Object> resultMap = XMLUtil.parse(paramXml.getBytes());
        
        //业务结果，有可能为空
        Object result_code = resultMap.get("result_code");
        
        if(null == result_code){
            //交易失败，不修改订单状态为失败，等待任务扫描查询结果
            log.info("wechatNotify 业务处理结果未返回" + paramXml);
            throw ICashierServiceException.RESULT_CODE_IS_NULL;
        }
        
        // 商户订单号
		String outTradeNo = (String) resultMap.get("out_trade_no");
		// 订单信息
		CashierChargeOrder cco = cashierChargeOrderService.queryByOrderId(outTradeNo);
		if (cco == null) {
			log.info("wechatNotify 支付订单不存在 orderId=" + outTradeNo);
			return WeChatConst.TRADE_FAIL;
		}
		
		// 总金额
		double totalFee = Double.parseDouble((String) resultMap.get("total_fee"));
		// 微信返回的金额为分，数据库存储的金额为元
		if (totalFee != cco.getMoney() * 100) {
			log.info("wechatNotify 微信返回金额与收银台不一致  orderId=" + outTradeNo + ",wechatTotalFee=" + totalFee + ",money=" + cco.getMoney());
			return WeChatConst.TRADE_FAIL;
		}
		
		// 业务处理状态
		int status = 0;
		if (WeChatConst.TRADE_FAIL.equals(result_code.toString())) {
			// 返回结果是失败
			status = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
		} else if (WeChatConst.TRADE_SUCCESS.equals(result_code.toString())) {
			// 交易结果成功
			status = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
		} else {
			// 未知的交易状态
			log.info("wechatNotify 未知的交易状态:" + result_code);
			return WeChatConst.TRADE_FAIL;
		}
        
		// 微信支付订单号
		String transactionId = (String) resultMap.get("transaction_id");
		// 支付完成时间，格式为yyyyMMddHHmmss
		String timeEnd = (String) resultMap.get("time_end");

		try {
			// 转换交易时间格式为yyyy-MM-dd HH:mm:ss
			Date tradeTime = DateHelper.convertToDate("yyyyMMddHHmmss", timeEnd);
			timeEnd = DateHelper.DateToString(null, tradeTime);
		} catch (ParseException e) {
			log.error("wechatNotify 银联返回交易时间格式错误", e);
        	throw ICashierServiceException.systemException;
		}
		
		// 错误代码
		String errorCode = (String) resultMap.get("err_code");
		String errorMsg = (String) resultMap.get("err_code_des");

		// 更新充值订单状态
		int res = cashierChargeOrderService.updateByOrderId(null, null, outTradeNo, timeEnd, status, transactionId, errorCode, errorMsg);
		if (res > 0) {
			// 如果更新成功，回推充值结果任务
			PushChargeTask pct = (PushChargeTask) SpringHelper.getBean("pushChargeTask");
			cco.setStatus(status);
			pct.setCashierChargeOrder(cco);
			TaskManagerFactory.getTaskManager(ICashierEnumConst.TaskManagerCode.PUSH_CHARGE_RESULT).addTask(pct);
		} else {
			// 如果是新失败，查询充值记录状态
			int state = cashierChargeOrderService.queryStatus(outTradeNo, null, null);
			if (state == ICashierEnumConst.CashierChargeStatus.WAIT.getStatus()) {
				log.info("wechatNotify 更新状态失败 orderId=" + outTradeNo);
				return WeChatConst.TRADE_FAIL;
			}
		}

		//返回处理交易订单状态
		return WeChatConst.TRADE_SUCCESS;
	}
	
	/**
     * 银联充值同步回调处理
     * @param unionpayParams
     * @param platId
     * @return
     * @throws BizException
     * @author zljun
     * @date 2016年6月7日
     */
	@Override
	public PayChannelChargeBackBO unionPayChargeBackDeal(
            Map<String, String> unionpayParams, String platId)
			throws BizException {
		PayChannelChargeBackBO resultBo = new PayChannelChargeBackBO();
		
		String encoding = unionpayParams.get("encoding");
		String orderId = unionpayParams.get("orderId");
		String txnAmt = unionpayParams.get("txnAmt");
		String respCode = unionpayParams.get("respCode");
		String respMsg = unionpayParams.get("respMsg");
		log.info("UnionPayChargeBack 充值同步通知参数：platId=" + platId + ",orderId=" + orderId + ",txnAmt=" + txnAmt + ",respCode=" + respCode + ",respMsg=" + respMsg);
		Map<String, String> valideData = null;
		if (null != unionpayParams && !unionpayParams.isEmpty()) {
			Iterator<Entry<String, String>> it = unionpayParams.entrySet().iterator();
			valideData = new HashMap<String, String>(unionpayParams.size());
			while (it.hasNext()) {
				Entry<String, String> e = it.next();
				String key = (String) e.getKey();
				String value = (String) e.getValue();
				try {
					value = new String(value.getBytes(encoding), encoding);
				} catch (UnsupportedEncodingException e1) {
					log.error("unionPayChargeBack", e1);
					throw ICashierServiceException.systemException;
				}
				valideData.put(key, value);
			}
		}
		if (!UnionPayAcpService.validate(valideData, encoding)) {
			log.info("unionPayChargeBack 验证签名结果[失败]");
			throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
		} 
		log.info("unionPayChargeBack 验证签名结果[成功]");
		CashierPlat cashierPlat = cashierPlatService.queryPlatById(platId);
        if (cashierPlat == null) {
        	log.info("unionPayChargeBack 获取平台信息失败 platId="+platId);
        	throw ICashierServiceException.PLAT_PAY_GATEWAY_NOT_EXIST;
        }
		int succStatus = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
        int failStatus = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
        int status = UnionPayment.TRADE_SUCCESS.equals(respCode) ? succStatus : failStatus;
        resultBo.setCallBackUrl(cashierPlat.getCallBackUrl());
        resultBo.setOrderId(orderId);
        resultBo.setStatus(status);
        return resultBo;
	}

	/**
     * 银联充值异步通知处理
     * @param unionpayParams
     * @return ok/error
     * @throws BizException
     * @author zljun
     * @date 2016年6月7日
     */
	@Override
	public String unionPayChargeNotifyDeal(Map<String, String> unionpayParams)
			throws BizException {
		
		String encoding = unionpayParams.get("encoding");
        //商户订单号
        String orderId = unionpayParams.get("orderId");
        String respCode = unionpayParams.get("respCode");
        //交易金额，单位分
        double txnAmt = Double.parseDouble(unionpayParams.get("txnAmt"));
        
        if (!UnionPayAcpService.validate(unionpayParams, encoding)) {
            //验证签名失败
            log.info("验证签名结果[失败] orderId:" + orderId);
            throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
        }
        log.info("验证签名结果[成功] orderId:" + orderId);

        // 订单信息
        CashierChargeOrder cco = cashierChargeOrderService.queryByOrderId(orderId);
        if (cco == null) {
            log.info("unionPayChargeNotifyDeal 支付订单不存在 orderId=" + orderId );
            throw ICashierServiceException.ORDER_NOT_EXIST;
        }
        
        if (txnAmt != cco.getMoney() * 100) {
        	// 第三方返回金额与收银台不一致    
            log.info("unionPayChargeNotifyDeal 银联返回金额与收银台不一致  orderId=" + cco.getOrderId() + ",txnAmt=" + txnAmt + ",money=" + cco.getMoney());
            throw ICashierServiceException.MONEY_DIFFER;
        }
        
        //业务处理状态
        int succStatus = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
        int failStatus = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
        int status = UnionPayment.TRADE_SUCCESS.equals(respCode) ? succStatus : failStatus;
        //银联流水号
        String queryId = unionpayParams.get("queryId");
        //交易传输时间,（MMDDHHmmss）24小时制收单机构对账时使用
        String traceTime = unionpayParams.get("traceTime");
        
        try {
            //转换交易时间格式为yyyy-MM-dd HH:mm:ss
            Date tradeTime = DateHelper.convertToDate("yyyyMMddHHmmss", DateHelper.formatDate("yyyy", new Date()) + traceTime);
            traceTime = DateHelper.DateToString(null, tradeTime);
        } catch (ParseException e) {
        	log.error("unionPayChargeNotifyDeal 银联返回交易时间格式错误", e);
        	throw ICashierServiceException.systemException;
        }
        
        // 更新充值订单状态
        int res = cashierChargeOrderService.updateByOrderId(null, null, orderId, traceTime, status, queryId , null, null);
        
        if(res > 0){
        	// 如果更新成功，回推充值结果任务
			PushChargeTask pct = (PushChargeTask) SpringHelper.getBean("pushChargeTask");
			cco.setStatus(status);
			pct.setCashierChargeOrder(cco);
			TaskManagerFactory.getTaskManager(ICashierEnumConst.TaskManagerCode.PUSH_CHARGE_RESULT).addTask(pct);
        } else {
            // 查询充值记录状态
            int state = cashierChargeOrderService.queryStatus(orderId, null, null);
            // 如果充值记录状态为待处理，返回交易失败
            if (state == ICashierEnumConst.CashierChargeStatus.WAIT.getStatus()) {
                log.info("unionPayChargeNotifyDeal 更新状态失败 orderId=" + orderId);
                return UnionPayConstants.TRADE_FAIL;
            }
        }
        
        return UnionPayConstants.TRADE_SUCCESS;
    }
	
	/**
     * 支付宝充值异步通知处理
     * @param alipayParams
     * @param platId
     * @param payChannelId
     * @param tradeType
     * @return success/fail
     * @throws BizException
     * @author zljun
     * @date 2016年6月7日
     */
	@Override
	public String alipayChargeNotifyDeal(Map<String, String> alipayParams,
                                         String platId, String payChannelId, int tradeType) throws BizException {

		int status = 0;
		String errorCode = null;
		String errorMsg = null;
		String msg = FAIL;
		String module = "";
		String outTradeNo = alipayParams.get("out_trade_no");// 商户订单号
		String tradeNo = alipayParams.get("trade_no");// 支付宝交易号
		String tradeStatus = alipayParams.get("trade_status");// 交易状态
		String gmtPayment = alipayParams.get("gmt_payment");// 交易付款时间
		double totalFee = Double.parseDouble(alipayParams.get("total_fee"));// 交易金额
		String alipaySignType = alipayParams.get("sign_type");// 加密类型
		log.info("alipayChargeNotify 充值异步通知参数：out_trade_no=" + outTradeNo + ",trade_no=" + tradeNo + ",totalFee=" + totalFee + ",trade_status=" + tradeStatus + ",platId=" + platId + ",sign_type=" + alipaySignType);

		CashierPayChannel cpc = cashierPayChannelService.queryByChannelId(payChannelId);
		if (cpc == null) {
			log.info("AlipayChargeNotifyDeal 支付渠道信息不存在 payChannelId=" + payChannelId);
			throw ICashierServiceException.PAY_CHANNEL_NOT_EXIST;
		}
		CashierPlatPaytype cpp = cashierPlatPaytypeService.queryEntity(platId, cpc.getPayChannelId());
		if (cpp == null) {
			log.info("AlipayChargeNotifyDeal 平台信息不存在 platId=" + platId + ",payChannelId=" + cpc.getPayChannelId());
			throw ICashierServiceException.PLAT_PAY_GATEWAY_NOT_EXIST;
		}
		CashierChargeOrder cco = cashierChargeOrderService.queryByOrderId(outTradeNo);
		if (cco == null) {
			log.info("AlipayChargeNotifyDeal 充值记录不存在 orderId=" + outTradeNo + ",platId=" + platId);
			throw ICashierServiceException.ORDER_NOT_EXIST;
		}
		String signType = cpp.getEncryptType() == ICashierEnumConst.CashierEncryptType.MD5.getEncryptType() ? ICashierEnumConst.CashierEncryptType.MD5.getDesc() : ICashierEnumConst.CashierEncryptType.RSA.getDesc();
		if (!signType.equals(alipaySignType)) {
			log.info("AlipayChargeNotifyDeal 平台加密类型已被修改  platId=" + platId + ",signType=" + signType + ",alipaySignType=" + alipaySignType);
			throw ICashierServiceException.ENCRYPTTYPE_DIFFER;
		}
		if (totalFee != cco.getMoney()) {
			log.info("AlipayChargeNotifyDeal 支付宝返回金额与收银台不一致  orderId=" + cco.getOrderId() + ",alipayTotalFee=" + totalFee + ",money=" + cco.getMoney());
			throw ICashierServiceException.MONEY_DIFFER;
		}
		String signKey = cpp.getEncryptType() == ICashierEnumConst.CashierEncryptType.MD5.getEncryptType() ? cpc.getMd5Key() : cpc.getThirdPubkey();
		String partner = cpc.getChannelUser();
		String verifyUrl = cpc.getPayUrl() + "?service=" + AlipayPayment.MODULE_NOTIFY_VERIFY + "&";
		boolean verify_result = AlipayNotify.verify(alipayParams, signType, signKey, partner, verifyUrl);
		if (verify_result) {// 验证成功
			int succStatus = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
			int failStatus = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
			if (AlipayPayment.TRADE_FINISHED.equals(tradeStatus) || AlipayPayment.TRADE_SUCCESS.equals(tradeStatus)) {
				status = succStatus;
			} else {// 失败
				status = failStatus;
				errorCode = tradeStatus;
				if (tradeType == ICashierEnumConst.CashierTradeType.WAP.getId()) {
					module = AlipayPaymentForCharge.MODULE_WAP_DIRECT_PAY;
				} else if (tradeType == ICashierEnumConst.CashierTradeType.WEB.getId()) {
					module = AlipayPaymentForCharge.MODULE_WEB_DIRECT_PAY;
				}
				module = AlipayPaymentForCharge.MODULE_WEB_DIRECT_PAY;
				errorMsg = AlipayErrorCode.getErrorMsg(module, errorCode);
			}
			int res = cashierChargeOrderService.updateByOrderId(null, null, outTradeNo, gmtPayment, status, tradeNo, errorCode, errorMsg);
			if (res > 0) {
				// 如果更新成功，回推充值结果任务
				PushChargeTask pct = (PushChargeTask) SpringHelper.getBean("pushChargeTask");
				cco.setStatus(status);
				pct.setCashierChargeOrder(cco);
				TaskManagerFactory.getTaskManager(ICashierEnumConst.TaskManagerCode.PUSH_CHARGE_RESULT).addTask(pct);
				msg = SUCC;
			} else {
				int state = cashierChargeOrderService.queryStatus(outTradeNo, null, null);
				if (state == ICashierEnumConst.CashierChargeStatus.WAIT.getStatus()) {
					log.info("AlipayChargeNotifyDeal 更新状态失败 orderId=" + outTradeNo + ",platId=" + platId);
				} else {
					msg = SUCC;
				}
			}
			if (SUCC.equals(msg)) {
				log.info("AlipayChargeNotifyDeal 充值异步通知处理完成 orderId=" + outTradeNo);
			}
		} else {// 验证失败
			log.info("AlipayChargeNotifyDeal 充值异步通知验证失败 orderId=" + outTradeNo);
			throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
		}
		return msg;
	}

	/**
     * 支付宝充值同步回调处理
     * @param alipayParams
     * @param platId
     * @param payChannelId
     * @return
     * @throws BizException
     * @author zljun
     * @date 2016年6月7日
     */
	@Override
	public PayChannelChargeBackBO alipayChargeBackDeal(
            Map<String, String> alipayParams, String platId, String payChannelId)
			throws BizException {
		PayChannelChargeBackBO resultBo = new PayChannelChargeBackBO();
        String outTradeNo = alipayParams.get("out_trade_no");//商户订单号
        String tradeNo = alipayParams.get("trade_no");//支付宝交易号
        String tradeStatus = alipayParams.get("trade_status");//交易状态
        String alipaySignType = alipayParams.get("sign_type");//加密类型
        double totalFee = Double.parseDouble(alipayParams.get("total_fee"));//总金额
        log.info("AlipayChargeBack 充值同步通知参数：out_trade_no=" + outTradeNo + ",trade_no=" + tradeNo + ",trade_status=" + tradeStatus + ",sign_type=" + alipaySignType + "total_fee=" + totalFee);
        CashierPayChannel cpc = cashierPayChannelService.queryByChannelId(payChannelId);
        if (cpc == null) {
        	log.info("AlipayChargeBackDeal 支付渠道信息不存在 payChannelId=" + payChannelId);
			throw ICashierServiceException.PAY_CHANNEL_NOT_EXIST;
        }
        CashierPlatPaytype cpp = cashierPlatPaytypeService.queryEntity(platId, cpc.getPayChannelId());
        if (cpp == null) {
        	log.info("AlipayChargeBackDeal 平台信息不存在 platId=" + platId + ",payChannelId=" + cpc.getPayChannelId());
			throw ICashierServiceException.PLAT_PAY_GATEWAY_NOT_EXIST;
        }
        CashierChargeOrder cco = cashierChargeOrderService.queryByOrderId(outTradeNo);
        if (cco == null) {
        	log.info("AlipayChargeBackDeal 充值记录不存在 orderId=" + outTradeNo + ",platId=" + platId);
			throw ICashierServiceException.ORDER_NOT_EXIST;
        }
        String signType = cpp.getEncryptType() == ICashierEnumConst.CashierEncryptType.MD5.getEncryptType() ? ICashierEnumConst.CashierEncryptType.MD5.getDesc() : ICashierEnumConst.CashierEncryptType.RSA.getDesc();
        if (!signType.equals(alipaySignType)) {
        	log.info("AlipayChargeBackDeal 平台加密类型已被修改  platId=" + platId + ",signType=" + signType + ",alipaySignType=" + alipaySignType);
			throw ICashierServiceException.ENCRYPTTYPE_DIFFER;
        }
        if (totalFee!=cco.getMoney()) {
        	log.info("alipayChargeNotify 支付宝返回金额与收银台不一致  orderId=" + cco.getOrderId() + ",alipayTotalFee=" + totalFee + ",money=" + cco.getMoney());
			throw ICashierServiceException.MONEY_DIFFER;
        }
        String signKey = cpp.getEncryptType() == ICashierEnumConst.CashierEncryptType.MD5.getEncryptType() ? cpc.getMd5Key() : cpc.getThirdPubkey();
        String partner = cpc.getChannelUser();
        String verifyUrl = cpc.getPayUrl() + "?service=" + AlipayPayment.MODULE_NOTIFY_VERIFY + "&";
        boolean verify_result = AlipayNotify.verify(alipayParams,signType,signKey,partner,verifyUrl);

        if (verify_result) {//验证成功
            log.info("AlipayChargeBack 充值同步通知验证成功");
            CashierPlat cashierPlat = cashierPlatService.queryPlatById(platId);
            if (cashierPlat == null) {
                log.info("alipayChargeBack 获取平台信息失败 platId=" + platId);
                throw ICashierServiceException.PLAT_PAY_GATEWAY_NOT_EXIST;
            }
            int succStatus = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
            int failStatus = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
			int status = (AlipayPayment.TRADE_FINISHED.equals(tradeStatus) || AlipayPayment.TRADE_SUCCESS.equals(tradeStatus)) ? succStatus : failStatus;
			resultBo.setOrderId(outTradeNo);
			resultBo.setCallBackUrl(cashierPlat.getCallBackUrl());
			resultBo.setStatus(status);
			return resultBo;
        } else {
        	//验证失败
        	log.info("AlipayChargeBack trade_no=" + tradeNo + " 充值同步通知验证失败");
        	throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
        }
	}

	@Override
	public PayChannelChargeBackBO bankcommChargeBackDeal(String notifyMsg,
			String platId) throws BizException {
		
		String signMsg = notifyMsg.substring(notifyMsg.lastIndexOf("|")+"|".length(),notifyMsg.length()); //获取签名信息
		String srcMsg = notifyMsg.substring(0,notifyMsg.lastIndexOf("|")+"|".length());
		if("".equals(BankcommCore.detachedVerify(srcMsg, signMsg))) {
			log.info("bankcommChargeBackDeal 验证签名结果[失败]");
			throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
		} 
		String[] notifyRes = srcMsg.split("\\|");
		String orderId = notifyRes[1];//订单号
		int tradeStatus = Integer.parseInt(notifyRes[9]);//交易状态 0处理中 1成功 2失败 3异常 9未处理
		log.info("bankcommChargeNotifyDeal orderId=" + orderId + ",tradeStatus="+ tradeStatus);
		CashierPlat cashierPlat = cashierPlatService.queryPlatById(platId);
        if (cashierPlat == null) {
        	log.info("bankcommChargeBackDeal 获取平台信息失败 platId="+platId);
        	throw ICashierServiceException.PLAT_PAY_GATEWAY_NOT_EXIST;
        }
		PayChannelChargeBackBO resultBo = new PayChannelChargeBackBO();
		int status = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
        if (tradeStatus==2 || tradeStatus==3) {//失败或异常
			status = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
		}
        resultBo.setCallBackUrl(cashierPlat.getCallBackUrl());
        resultBo.setOrderId(orderId);
        resultBo.setStatus(status);
        return resultBo;
	}

	@Override
	public void bankcommChargeNotifyDeal(String notifyMsg)
			throws BizException {
		String traceTime = null;
		String signMsg = notifyMsg.substring(notifyMsg.lastIndexOf("|")+"|".length(),notifyMsg.length()); //获取签名信息
		String srcMsg = notifyMsg.substring(0,notifyMsg.lastIndexOf("|")+"|".length());
		if("".equals(BankcommCore.detachedVerify(srcMsg, signMsg))) {
			log.info("bankcommChargeNotifyDeal 验证签名结果[失败]");
			throw ICashierServiceException.NOTIFY_CHECK_NOT_PASSED;
		} 
		String[] notifyRes = srcMsg.split("\\|");
		String orderId = notifyRes[1];//订单号
		double txnAmt = Double.parseDouble(notifyRes[2]);//交易金额
		String tradeDate = notifyRes[6];//交易日期
		String tradeTime = notifyRes[7];//交易时间
		String serialNo = notifyRes[8];//流水号
		int tradeStatus = Integer.parseInt(notifyRes[9]);//交易状态 0处理中 1成功 2失败 3异常 9未处理
		log.info("bankcommChargeNotifyDeal orderId=" + orderId + ",txnAmt="
				+ txnAmt + ",tradeDate=" + tradeDate + ",tradeTime="
				+ tradeTime + ",serialNo=" + serialNo + ",tradeStatus="
				+ tradeStatus);
		// 订单信息
        CashierChargeOrder cco = cashierChargeOrderService.queryByOrderId(orderId);
        if (cco == null) {
            log.info("bankcommChargeNotifyDeal 支付订单不存在 orderId=" + orderId );
            throw ICashierServiceException.ORDER_NOT_EXIST;
        }
        if (txnAmt != cco.getMoney()) {
        	// 第三方返回金额与收银台不一致    
            log.info("bankcommChargeNotifyDeal 银联返回金额与收银台不一致  orderId=" + cco.getOrderId() + ",txnAmt=" + txnAmt + ",money=" + cco.getMoney());
            throw ICashierServiceException.MONEY_DIFFER;
        }
        
        //业务处理状态
        int status = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
        if (tradeStatus!=1 && tradeStatus!=2 && tradeStatus!=3) {//非处理完成状态
        	log.info("bankcommChargeNotifyDeal 未处理完成，结束运行！  tradeStatus="+tradeStatus);
			return;
		}
        if (tradeStatus==2 || tradeStatus==3) {//失败或异常
			status = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
		}
        try {
            //转换交易时间格式为yyyy-MM-dd HH:mm:ss
            Date tradeDateTime = DateHelper.convertToDate("yyyyMMddHHmmss", tradeDate+tradeTime);
            traceTime = DateHelper.DateToString(null, tradeDateTime);
        } catch (ParseException e) {
        	log.error("bankcommChargeNotifyDeal 交易时间转换错误", e);
        	throw ICashierServiceException.systemException;
        }
        
        // 更新充值订单状态
        int res = cashierChargeOrderService.updateByOrderId(null, null, orderId, traceTime, status, serialNo , null, null);
        
        if(res > 0){
        	// 如果更新成功，回推充值结果任务
			PushChargeTask pct = (PushChargeTask) SpringHelper.getBean("pushChargeTask");
			cco.setStatus(status);
			pct.setCashierChargeOrder(cco);
			TaskManagerFactory.getTaskManager(ICashierEnumConst.TaskManagerCode.PUSH_CHARGE_RESULT).addTask(pct);
        } else {
            // 查询充值记录状态
            int state = cashierChargeOrderService.queryStatus(orderId, null, null);
            // 如果充值记录状态为待处理，返回交易失败
            if (state == ICashierEnumConst.CashierChargeStatus.WAIT.getStatus()) {
                log.info("bankcommChargeNotifyDeal 更新状态失败 orderId=" + orderId);
            }
        }
	}
	
}
